/***
 * * PROJECT
 * *    ATaG
 * * VERSION
 * *    $Revision: 1.6 $
 * * DATE
 * *    $Date: 2008/04/21 08:29:30 $
 * * LOG
 * *    $Log: SimpleGreedyAssigner.java,v $
 * *    Revision 1.6  2008/04/21 08:29:30  animesh
 * *    added debug prints
 * *
 * *    Revision 1.5  2008/04/21 08:24:51  animesh
 * *    fixed bug in MeasuringUtils to check if the edge is mapped, before adding cost.
 * *
 * *    Revision 1.4  2008/04/19 09:15:52  animesh
 * *    multipath done
 * *
 * *    Revision 1.3  2008/01/03 20:07:11  animesh
 * *    no message
 * *
 * *    Revision 1.2  2007/11/26 00:05:56  animesh
 * *    added INFINITY as a parameter for greedy task assigner, and allocation of an edge for a vertex is skipped if the task allocation cost itself is infinity.
 * *
 * *
 ***/
package atag.compiler.powerassigner;

import atag.common.*;
import atag.compiler.*;
import java.util.ArrayList;

/**
 *
 * @author Animesh
 */
public class SimpleGreedyAssigner implements TaskAssigner {

    //public static final double INFINITY = 10e9;
    public static final boolean debugPrint = false;

    /**
     * Creates a new instance of SimpleGreedyAssigner
     */
    public SimpleGreedyAssigner() {
    }

    /**
     * @deprecated
     * The function that assigns tasks.
     * @param aP The ATaG program
     * @param itP The ITaG version of aP
     * @param caProgram the composed ATaG program
     * @param nTopo The network, with all nodes
     * @param randomSeed The seed for the random number generator
     */
    public void assignTasks(ATaGProgram aP, ITaGProgram itP,
            ComposedATaG caProgram, NetworkTopology nTopo, int randomSeed) {
        //fill in T[][]
        //first count the number of tasks
        final double INFINITY = 10e9;

        int m = 0;
        for (ATaGTaskDeclaration at : aP.getTaskList()) {
            int instType = at.getLocation()[0];
            int instParam = at.getLocation()[1];
            int atID = at.getID();

            if (at.getAssignedTo().size() == 0) {
                // not assigned yet. Assign now
                switch (instType) {
                    case ATaGTaskDeclaration.INSTANTIATION_ONE_ON_NODE_ID:
                        m++;
                        break;
                    case ATaGTaskDeclaration.INSTANTIATION_NODES_PER_INSTANCE:
                        // instantiate on one of each
                        if (at.getNeededAttribute() != null) {
                            // find all nodes with that attribute, and assign this task
                            // on them
                            m = m + nTopo.getNodesWithAttribute(at.getNeededAttribute()).size();
                        } else {
                            // no needed Attribute. Assign on all.
                            m = m + nTopo.getNumberOfNodes();
                        }
                        break;
                    case ATaGTaskDeclaration.INSTANTIATION_PARTITION_PER_INSTANCE:
                        // assume that regionIDs are from 0 to k-1 only
                        // that means no missing regionIDs
                        m = m + nTopo.numberOfRegions(at.getMyRegionName());

                        break;
                }
            }
        }

        //we have m .. now to fill up T[][]
        int n = nTopo.getNumberOfNodes();
        int numberOfAbstractTasks = aP.getTaskList().size();

        double[][] T = new double[m][n];
        int[] instanceCount = new int[numberOfAbstractTasks];
        int[] instanceBegin = new int[numberOfAbstractTasks];

        int taskCount = 0;
        //initialize T
        for (int i = 0; i < m; i++) {
            for (int k = 0; k < n; k++) {
                T[i][k] = INFINITY;
            }
        }


        //now update entries in the T
        for (ATaGTaskDeclaration at : aP.getTaskList()) {
            int instType = at.getLocation()[0];
            int instParam = at.getLocation()[1];
            int atID = at.getID();

            if (at.getAssignedTo().size() == 0) {
                // not assigned yet. Assign now
                switch (instType) {
                    case ATaGTaskDeclaration.INSTANTIATION_ONE_ON_NODE_ID:
                        instanceBegin[atID] = taskCount;
                        instanceCount[1] = 1;
                        T[taskCount++][instParam] = 0;//assigning here is free
                        break;
                    case ATaGTaskDeclaration.INSTANTIATION_NODES_PER_INSTANCE:
                        // instantiate on one of each
                        if (at.getNeededAttribute() != null) {
                            // find all nodes with that attribute, and assign this task
                            // on them
                            //TODO -- mod to T[][]
                            m = m + nTopo.getNodesWithAttribute(at.getNeededAttribute()).size();
                        } else {
                            // no needed Attribute. Assign on all.
                            //TODO -- mod to T[][]
                            m = m + nTopo.getNumberOfNodes();
                        }
                        break;
                    case ATaGTaskDeclaration.INSTANTIATION_PARTITION_PER_INSTANCE:
                        // assume that regionIDs are from 0 to k-1 only
                        // that means no missing regionIDs
                        //TODO -- mod to T[][]
                        m = m + nTopo.numberOfRegions(at.getMyRegionName());

                        break;
                }
            }
        }

    }

    /**
     * prints stats for this assignment
     * @param m Number of tasks
     * @param n Number of nodes
     * @param T T_ik = cost of setting task i on node k
     * @param R R_ijk = cost at k for sending one data unit from i to j
     * @param f f_i = frequency of task i
     * @param s s_ij = amount of data transferred on (i,j) edge in DE
     * @param e0 e0_k = initial energy at node k
     */
    public static int[][] returnAssignmentMinMaxCost(int m, int n, double[][] T,
            double[][][] R, double[] f,
            double[][] s, double[] e0,
            double INFINITY) {


        //initialize the edges
        int count = 0;
        ArrayList<DAGEdge> edges = new ArrayList();

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < m; j++) {
                if (s[i][j] != 0) {
                    //edge i --> j exists
                    edges.add(new DAGEdge(count++, i, j, f[i] * s[i][j]));
                }
            }
        }

        int numberOfEdges = count;

        //sort the edges
        int[] sortedEdges = new int[numberOfEdges];

        for (int edgecount = 0; edgecount < numberOfEdges; edgecount++) {
            DAGEdge e = edges.get(edgecount);
            for (int tempi = edgecount - 1; tempi >= 0; tempi--) {
                //tempi = edgecount -1 to 0
                if (e.getCost() > edges.get(sortedEdges[tempi]).getCost()) {
                    //move tempi one notch down
                    sortedEdges[tempi + 1] = sortedEdges[tempi];
                    sortedEdges[tempi] = edgecount;
                } else {
                    //no more insertion possible.
                    sortedEdges[tempi + 1] = edgecount; //redundant?
                    break;
                }//if
            }//for
        }//for

        //initialize arrays
        int[][] x = new int[m][n];
        int[] assignedTo = new int[m];

        for (int i = 0; i < m; i++) {
            assignedTo[i] = -1;//invalid
            for (int k = 0; k < n; k++) {
                x[i][k] = 0;
            }
        }

        //now try adding edges
        for (int edgecount = 0; edgecount < numberOfEdges; edgecount++) {
            DAGEdge e = edges.get(sortedEdges[edgecount]);
            int i = e.getSource();
            int j = e.getDestination();
            int starti, endi, startj, endj;

            if (assignedTo[i] == -1) {
                starti = 0;
                endi = n - 1;
            } else {
                starti = endi = assignedTo[i];
            }

            if (assignedTo[j] == -1) {
                startj = 0;
                endj = n - 1;
            } else {
                startj = endj = assignedTo[j];
            }

            //todo - find a more sensible
            double minCost = INFINITY * INFINITY;
            int mini = -1;
            int minj = -1;

            for (int tempi = starti; tempi <= endi; tempi++) {
                //debug
//                System.out.println("i = "+i+", j = "+j+", tempi = "+tempi+"," +
//                        " cost = "+ T[i][tempi]);
                //if the cost of assignment is infinity. skip
                if (T[i][tempi] >= INFINITY) {
                    continue;//jump to end of for loop
                }
                //temporarily assign i to tempi
                x[i][tempi] = 1;

                //for new, faster evaluation.
                //store away the current assignment of i
                int tempiassignment = assignedTo[i];
                assignedTo[i] = tempi;


                for (int tempj = startj; tempj <= endj; tempj++) {
                    //debug
//                    System.out.println("\tj = "+j+", tempj = "+tempj+", " +
//                            "cost = "+T[j][tempj]);
                    //if the cost of assignment is infinity. skip
                    if (T[j][tempj] >= INFINITY) {
                        continue;//jump to end of for loop
                    }


                    //temporarily assign j to tempj
                    x[j][tempj] = 1;
                    //for new, faster evaluation.
                    //store away the current assignment of i
                    int tempjassignment = assignedTo[j];
                    assignedTo[j] = tempj;

                    //double tempcost = MeasuringUtils.maxCost(m,n,T,R,f,s,e0,x);
                    double tempcost = MeasuringUtils.maxCost(m, n, T, R, f, s, e0, assignedTo);

                    if (tempcost < minCost) {
                        minCost = tempcost;
                        mini = tempi;
                        minj = tempj;
                    //debug
//                        System.out.println("\tmini = "+mini+", minj = "+minj+", " +
//                                "mincost = "+minCost);
                    }//if
                    //unassign
                    x[j][tempj] = 0;
                    assignedTo[j] = tempjassignment;

                }
                x[i][tempi] = 0;
                assignedTo[i] = tempiassignment;
            }
            //assign i to mini and j to minj
            if(debugPrint)
                System.out.println("Assigning (" + i + "," + j + ") [cost:" + e.getCost() + "] to (" + mini + "," + minj + ")");
            x[i][mini] = 1;
            assignedTo[i] = mini;
            x[j][minj] = 1;
            assignedTo[j] = minj;
        }//for each edge
        return x;

    }

    /**
     * @returns assigned such as to minimize total cost
     * @param m Number of tasks
     * @param n Number of nodes
     * @param T T_ik = cost of setting task i on node k
     * @param R R_ijk = cost at k for sending one data unit from i to j
     * @param f f_i = frequency of task i
     * @param s s_ij = amount of data transferred on (i,j) edge in DE
     * @param e0 e0_k = initial energy at node k
     */
    public static int[][] returnAssignmentMinTotalCost(int m, int n, double[][] T,
            double[][][] R, double[] f,
            double[][] s, double[] e0,
            double INFINITY) {


        //initialize the edges
        int count = 0;
        ArrayList<DAGEdge> edges = new ArrayList();

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < m; j++) {
                if (s[i][j] != 0) {
                    //edge i --> j exists
                    edges.add(new DAGEdge(count++, i, j, f[i] * s[i][j]));
                }
            }
        }

        int numberOfEdges = count;

        //sort the edges
        int[] sortedEdges = new int[numberOfEdges];

        for (int edgecount = 0; edgecount < numberOfEdges; edgecount++) {
            DAGEdge e = edges.get(edgecount);
            for (int tempi = edgecount - 1; tempi >= 0; tempi--) {
                //tempi = edgecount -1 to 0
                if (e.getCost() > edges.get(sortedEdges[tempi]).getCost()) {
                    //move tempi one notch down
                    sortedEdges[tempi + 1] = sortedEdges[tempi];
                    sortedEdges[tempi] = edgecount;
                } else {
                    //no more insertion possible.
                    sortedEdges[tempi + 1] = edgecount; //redundant?
                    break;
                }//if
            }//for
        }//for

        //initialize arrays
        int[][] x = new int[m][n];
        int[] assignedTo = new int[m];

        for (int i = 0; i < m; i++) {
            assignedTo[i] = -1;//invalid
            for (int k = 0; k < n; k++) {
                x[i][k] = 0;
            }
        }

        //now try adding edges
        for (int edgecount = 0; edgecount < numberOfEdges; edgecount++) {
            DAGEdge e = edges.get(sortedEdges[edgecount]);
            int i = e.getSource();
            int j = e.getDestination();
            int starti, endi, startj, endj;

            if (assignedTo[i] == -1) {
                starti = 0;
                endi = n - 1;
            } else {
                starti = endi = assignedTo[i];
            }

            if (assignedTo[j] == -1) {
                startj = 0;
                endj = n - 1;
            } else {
                startj = endj = assignedTo[j];
            }

            //todo - find a more sensible
            double minCost = INFINITY * INFINITY;
            int mini = -1;
            int minj = -1;

            for (int tempi = starti; tempi <= endi; tempi++) {
                //debug
//                System.out.println("i = "+i+", j = "+j+", tempi = "+tempi+"," +
//                        " cost = "+ T[i][tempi]);
                //if the cost of assignment is infinity. skip
                if (T[i][tempi] >= INFINITY) {
                    continue;//jump to end of for loop
                }
                //temporarily assign i to tempi
                x[i][tempi] = 1;

                //for new, faster evaluation.
                //store away the current assignment of i
                int tempiassignment = assignedTo[i];
                assignedTo[i] = tempi;


                for (int tempj = startj; tempj <= endj; tempj++) {
                    //debug
//                    System.out.println("\tj = "+j+", tempj = "+tempj+", " +
//                            "cost = "+T[j][tempj]);
                    //if the cost of assignment is infinity. skip
                    if (T[j][tempj] >= INFINITY) {
                        continue;//jump to end of for loop
                    }


                    //temporarily assign j to tempj
                    x[j][tempj] = 1;
                    //for new, faster evaluation.
                    //store away the current assignment of i
                    int tempjassignment = assignedTo[j];
                    assignedTo[j] = tempj;

                    //double tempcost = MeasuringUtils.maxCost(m,n,T,R,f,s,e0,x);
                    double tempcost = MeasuringUtils.totalCost(m, n, T, R, f, s, e0, assignedTo);

                    if (tempcost < minCost) {
                        minCost = tempcost;
                        mini = tempi;
                        minj = tempj;
                    //debug
//                        System.out.println("\tmini = "+mini+", minj = "+minj+", " +
//                                "mincost = "+minCost);
                    }//if
                    //unassign
                    x[j][tempj] = 0;
                    assignedTo[j] = tempjassignment;

                }
                x[i][tempi] = 0;
                assignedTo[i] = tempiassignment;
            }
            //assign i to mini and j to minj
            if(debugPrint)
                System.out.println("Assigning (" + i + "," + j + ") [cost:" + e.getCost() + "] to (" + mini + "," + minj + ")");
            x[i][mini] = 1;
            assignedTo[i] = mini;
            x[j][minj] = 1;
            assignedTo[j] = minj;
        }//for each edge
        return x;

    }

    /**
     * prints stats for this assignment
     * @param m Number of tasks
     * @param n Number of nodes
     * @param numPaths Number of possible paths
     * @param T T_ik = cost of setting task i on node k
     * @param R R_ijk = cost at k for sending one data unit from i to j
     * @param f f_i = frequency of task i
     * @param s s_ij = amount of data transferred on (i,j) edge in DE
     * @param e0 e0_k = initial energy at node k
     */
    public static TaskAndRouteMapping returnAssignmentMultiPathMinMaxCost(int m, int n, int numPaths,
            double[][] T,
            double[][][][] MR, double[] f,
            double[][] s, double[] e0,
            double INFINITY) {


        //initialize the edges
        int count = 0;
        ArrayList<DAGEdge> edges = new ArrayList();

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < m; j++) {
                if (s[i][j] != 0) {
                    //edge i --> j exists
                    edges.add(new DAGEdge(count++, i, j, f[i] * s[i][j]));
                }
            }
        }

        int numberOfEdges = count;

        //sort the edges
        int[] sortedEdges = new int[numberOfEdges];

        for (int edgecount = 0; edgecount < numberOfEdges; edgecount++) {
            DAGEdge e = edges.get(edgecount);
            for (int tempi = edgecount - 1; tempi >= 0; tempi--) {
                //tempi = edgecount -1 to 0
                if (e.getCost() > edges.get(sortedEdges[tempi]).getCost()) {
                    //move tempi one notch down
                    sortedEdges[tempi + 1] = sortedEdges[tempi];
                    sortedEdges[tempi] = edgecount;
                } else {
                    //no more insertion possible.
                    sortedEdges[tempi + 1] = edgecount; //redundant?
                    break;
                }//if
            }//for
        }//for

        //initialize arrays
        int[][] x = new int[m][n];
        int[] assignedTo = new int[m];


        for (int i = 0; i < m; i++) {
            assignedTo[i] = -1;//invalid
            for (int k = 0; k < n; k++) {
                x[i][k] = 0;
            }
        }

        int[][] pathChoice = new int[m][m];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < m; j++) //set to invalid
            {
                pathChoice[i][j] = -1;
            }
        }

        //now try adding edges
        for (int edgecount = 0; edgecount < numberOfEdges; edgecount++) {
            DAGEdge e = edges.get(sortedEdges[edgecount]);
            int i = e.getSource();
            int j = e.getDestination();
            int starti, endi, startj, endj;

            if (assignedTo[i] == -1) {
                starti = 0;
                endi = n - 1;
            } else {
                starti = endi = assignedTo[i];
            }

            if (assignedTo[j] == -1) {
                startj = 0;
                endj = n - 1;
            } else {
                startj = endj = assignedTo[j];
            }

            //todo - find a more sensible
            double minCost = INFINITY * INFINITY;
            int mini = -1;
            int minj = -1;
            int minRho = -1;

            for (int tempi = starti; tempi <= endi; tempi++) {
                //debug
//                System.out.println("i = "+i+", j = "+j+", tempi = "+tempi+"," +
//                        " cost = "+ T[i][tempi]);
                //if the cost of assignment is infinity. skip
                if (T[i][tempi] >= INFINITY) {
                    continue;//jump to end of for loop
                }
                //temporarily assign i to tempi
                x[i][tempi] = 1;

                //for new, faster evaluation.
                //store away the current assignment of i
                int tempiassignment = assignedTo[i];
                assignedTo[i] = tempi;


                for (int tempj = startj; tempj <= endj; tempj++) {
                    //debug
//                    System.out.println("\tj = "+j+", tempj = "+tempj+", " +
//                            "cost = "+T[j][tempj]);
                    //if the cost of assignment is infinity. skip
                    if (T[j][tempj] >= INFINITY) {
                        continue;//jump to end of for loop
                    }


                    //temporarily assign j to tempj
                    x[j][tempj] = 1;
                    //for new, faster evaluation.
                    //store away the current assignment of i
                    int tempjassignment = assignedTo[j];
                    assignedTo[j] = tempj;

                    for (int tempRho = 0; tempRho < numPaths; tempRho++) {

                        //don't even try this path if node tempi spends infinite costs here
                        if (MR[tempi][tempj][tempi][tempRho] >= GraphUtils.INFINITY) {
                            continue;
                        }

                        pathChoice[i][j] = tempRho;

                        double tempcost = MeasuringUtils.maxMultiPathCost(m, n, numPaths, T, MR, f, s, e0, assignedTo, pathChoice);

                        if (tempcost < minCost) {
                            minCost = tempcost;
                            mini = tempi;
                            minj = tempj;
                            minRho = tempRho;
                        //debug
//                        System.out.println("\tmini = "+mini+", minj = "+minj+", " +
//                                "mincost = "+minCost);
                        }//if

                        //unassign
                        pathChoice[i][j] = -1;

                    }
                    //unassign
                    x[j][tempj] = 0;
                    assignedTo[j] = tempjassignment;

                }
                x[i][tempi] = 0;
                assignedTo[i] = tempiassignment;
            }
            //assign i to mini and j to minj
            if(debugPrint)
                System.out.println("Assigning (" + i + "," + j + ") [cost:" + e.getCost() + "] to (" + mini + "," + minj + "), Path " + minRho);
            x[i][mini] = 1;
            assignedTo[i] = mini;
            x[j][minj] = 1;
            assignedTo[j] = minj;
            pathChoice[i][j] = minRho;
            if(minRho == -1){
                System.err.println("oops .. no path for task-edge" + i + " " + j);
            }

        }//for each edge
        return new TaskAndRouteMapping(x, pathChoice);

    }

    /**
     * @returns assigned such as to minimize total cost
     * @param m Number of tasks
     * @param n Number of nodes
     * @param T T_ik = cost of setting task i on node k
     * @param R R_ijk = cost at k for sending one data unit from i to j
     * @param f f_i = frequency of task i
     * @param s s_ij = amount of data transferred on (i,j) edge in DE
     * @param e0 e0_k = initial energy at node k
     */
    public static TaskAndRouteMapping returnAssignmentMultiPathMinTotalCost(int m, int n, int numPaths, double[][] T,
            double[][][][] MR, double[] f,
            double[][] s, double[] e0,
            double INFINITY) {


        //initialize the edges
        int count = 0;
        ArrayList<DAGEdge> edges = new ArrayList();

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < m; j++) {
                if (s[i][j] != 0) {
                    //edge i --> j exists
                    edges.add(new DAGEdge(count++, i, j, f[i] * s[i][j]));
                }
            }
        }

        int numberOfEdges = count;

        //sort the edges
        int[] sortedEdges = new int[numberOfEdges];

        for (int edgecount = 0; edgecount < numberOfEdges; edgecount++) {
            DAGEdge e = edges.get(edgecount);
            for (int tempi = edgecount - 1; tempi >= 0; tempi--) {
                //tempi = edgecount -1 to 0
                if (e.getCost() > edges.get(sortedEdges[tempi]).getCost()) {
                    //move tempi one notch down
                    sortedEdges[tempi + 1] = sortedEdges[tempi];
                    sortedEdges[tempi] = edgecount;
                } else {
                    //no more insertion possible.
                    sortedEdges[tempi + 1] = edgecount; //redundant?
                    break;
                }//if
            }//for
        }//for

        //initialize arrays
        int[][] x = new int[m][n];
        int[] assignedTo = new int[m];

        for (int i = 0; i < m; i++) {
            assignedTo[i] = -1;//invalid
            for (int k = 0; k < n; k++) {
                x[i][k] = 0;
            }
        }

        int[][] pathChoice = new int[m][m];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < m; j++) //set to invalid
            {
                pathChoice[i][j] = -1;
            }
        }

        //now try adding edges
        for (int edgecount = 0; edgecount < numberOfEdges; edgecount++) {
            DAGEdge e = edges.get(sortedEdges[edgecount]);
            int i = e.getSource();
            int j = e.getDestination();
            int starti, endi, startj, endj;

            if (assignedTo[i] == -1) {
                starti = 0;
                endi = n - 1;
            } else {
                starti = endi = assignedTo[i];
            }

            if (assignedTo[j] == -1) {
                startj = 0;
                endj = n - 1;
            } else {
                startj = endj = assignedTo[j];
            }

            //todo - find a more sensible
            double minCost = INFINITY * INFINITY;
            int mini = -1;
            int minj = -1;
            int minRho = -1;

            for (int tempi = starti; tempi <= endi; tempi++) {
                //debug
//                System.out.println("i = "+i+", j = "+j+", tempi = "+tempi+"," +
//                        " cost = "+ T[i][tempi]);
                //if the cost of assignment is infinity. skip
                if (T[i][tempi] >= INFINITY) {
                    continue;//jump to end of for loop
                }
                //temporarily assign i to tempi
                x[i][tempi] = 1;

                //for new, faster evaluation.
                //store away the current assignment of i
                int tempiassignment = assignedTo[i];
                assignedTo[i] = tempi;


                for (int tempj = startj; tempj <= endj; tempj++) {
                    //debug
//                    System.out.println("\tj = "+j+", tempj = "+tempj+", " +
//                            "cost = "+T[j][tempj]);
                    //if the cost of assignment is infinity. skip
                    if (T[j][tempj] >= INFINITY) {
                        continue;//jump to end of for loop
                    }


                    //temporarily assign j to tempj
                    x[j][tempj] = 1;
                    //for new, faster evaluation.
                    //store away the current assignment of i
                    int tempjassignment = assignedTo[j];
                    assignedTo[j] = tempj;

                    for (int tempRho = 0; tempRho < numPaths; tempRho++) {

                        //don't even try this path if node tempi spends infinite costs here
                        if (MR[tempi][tempj][tempi][tempRho] >= GraphUtils.INFINITY) {
                            continue;
                        }

                        pathChoice[i][j] = tempRho;

                        double tempcost = MeasuringUtils.totalMultiPathCost(m, n, numPaths, T, MR, f, s, e0, assignedTo, pathChoice);

                        if (tempcost < minCost) {
                            minCost = tempcost;
                            mini = tempi;
                            minj = tempj;
                            minRho = tempRho;
                        //debug
//                        System.out.println("\tmini = "+mini+", minj = "+minj+", " +
//                                "mincost = "+minCost);
                        }//if

                        //unassign
                        pathChoice[i][j] = -1;
                    }
                    //unassign
                    x[j][tempj] = 0;
                    assignedTo[j] = tempjassignment;

                }
                x[i][tempi] = 0;
                assignedTo[i] = tempiassignment;
            }
            //assign i to mini and j to minj
            System.out.println("Assigning (" + i + "," + j + ") [cost:" + e.getCost() + "] to (" + mini + "," + minj + "), Path " + minRho);
            x[i][mini] = 1;
            assignedTo[i] = mini;
            x[j][minj] = 1;
            assignedTo[j] = minj;
            pathChoice[i][j] = minRho;
        }//for each edge
        return new TaskAndRouteMapping(x, pathChoice);

    }
    }

class DAGEdge {

    int ID;
    int source;
    int destination;
    double cost;

    public DAGEdge(int ID, int source, int destination, double cost) {
        this.ID = ID;
        this.source = source;
        this.destination = destination;
        this.cost = cost;
    }

    public int getID() {
        return ID;
    }

    public int getSource() {
        return source;
    }

    public int getDestination() {
        return destination;
    }

    public double getCost() {
        return cost;
    }
    }
